#include "cansettings.h"
#include "ui_cansettings.h"



//outside initialization instance ptr  canfilemap   veccanmodebitrate
CanSettings* CanSettings::instance = nullptr;

QMap<QString,QString> CanSettings::canfilemap;
QVector<CanSettings::CanModeBitrate>   CanSettings::veccanmodebitrate;
CanSettings::CanSettings(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::CanSettings)
{
    ui->setupUi(this);
    //setting groupBoxCanInfo false
    ui->groupBoxCanInfo->setVisible(false);
    //set default bit rate
    ui->canlineEditBitRate->setText("500.0");
}

CanSettings::~CanSettings()
{
    delete ui;
}

//make it mutex
CanSettings* CanSettings::getInstance()
{
    //multi thread to access it ,may cause compete.
    static QMutex mutex;
    if(!instance)
    {
        //make it to lock to solve thread saftey
        QMutexLocker locker(&mutex);
        if(!instance)
        {
            qDebug()<<"new CanSettings";
            instance = new CanSettings;
        }
    }
    return instance;
}



void CanSettings::onTreeViewMenuRequested(const QPoint &pos)
{
    QModelIndex curIndex =  ui->treeViewCan->indexAt(pos);

    if (curIndex.isValid()) // chose index
    {
        if(curIndex.data().toString()=="DateBases")
        {

            QIcon view = QApplication::style()->standardIcon(QStyle::SP_FileIcon);
            QIcon test = QApplication::style()->standardIcon(QStyle::SP_FileIcon);

            // create menus
            QMenu menu;
            menu.addAction(view, tr("Open dbc file"), this, &CanSettings::onActionView);
            menu.addSeparator();
            menu.addAction(test, tr("test"), this, &CanSettings::onActionTest);
            menu.exec(QCursor::pos());
        }
        else if(curIndex.data().toString()=="Setup")
        {
            //set CAN X to groupBoxCanInfo tittle
            ui->groupBoxCanInfo->setTitle(curIndex.parent().data().toString());
            ui->groupBoxCanInfo->setVisible(true);
        }
        else
        {
             ui->groupBoxCanInfo->setVisible(false);
        }

    }
}


void CanSettings::onActionView()
{
    QFont *fontitem=new QFont();
    fontitem->setFamily("modern No.20");
    fontitem->setPointSize(14);

    QModelIndex curIndex =  ui->treeViewCan->currentIndex();
    QModelIndex index = curIndex.sibling(curIndex.row(), 0); // 获取同一行第0列
    if(index.isValid())
    {
        QString  fileName;

        fileName = QFileDialog::getOpenFileName(
            this,
            tr("Open ."),
            "D:/",
            tr("text files(*.dbc );;All files(*.*)"));
        if (fileName.isEmpty()) {
            QMessageBox::warning(this, "Warning!", "Failed to open the file!");
        }
        else {
            QFileInfo fileInfo(fileName);
            QString fileName_name = fileInfo.baseName();

            //update treeview
            //
            QStandardItem *item_sub_db = new QStandardItem(QIcon(":/res/db.ico"),fileName_name); //
            item_sub_db->setFont(*fontitem);
            //get treeview model
            QStandardItemModel* model = qobject_cast<QStandardItemModel*>(ui->treeViewCan->model());

            QStandardItem* rootNode = model->itemFromIndex(curIndex);
            // check duplicated name
            bool duplicateFound = false;
            for (int row = 0; row < rootNode->rowCount(); ++row) {
                QStandardItem* childNode = rootNode->child(row, 0);
                if (childNode->text() == fileName_name) {
                    qDebug()<<"print"<<childNode->text();
                    duplicateFound = true;
                    rootNode->removeRow(row);
                    break;
                }
            }

            if (!duplicateFound) {
                //only one .dbc files in CAN X
                rootNode->removeRow(0);
                //stored can and filename to canfilemap
                CanSettings::setcanfilemap(rootNode->parent()->text(),fileName);
                //show this map in console
                QMapIterator<QString, QString> iterator(CanSettings::getcanfilemap());
                while (iterator.hasNext()) {
                    iterator.next();
                    qDebug() << iterator.key() << ":" << iterator.value();
                }
                qDebug()<<CanSettings::getcanfilemap();
                //delete former dbc files in trees
                rootNode->appendRow(item_sub_db);
                //
            }

        }

        QMessageBox::information(this, tr("打开文件"), index.data().toString());
    }
}
//set canfilemap
bool CanSettings::setcanfilemap(QString canname, QString dbfilename)
{
    CanSettings::canfilemap.insert(canname,dbfilename);
    return true;
}
//get canfilemap
QMap<QString, QString> CanSettings::getcanfilemap()
{
    return CanSettings::canfilemap;
}

QVector<CanSettings::CanModeBitrate> CanSettings::getvecmodbitrate()
{
    return CanSettings::veccanmodebitrate;
}

bool CanSettings::setvecmodbitrate(CanModeBitrate &canmbr)
{
    //make unique mapped about can and mode bitrate
    if(getvecmodbitrate().size() ==0)
    {
        //add new one
        getvecmodbitrate().append(canmbr);

    }
    else
    {
        //update that one
        for(int canbitcount = 0;canbitcount < getvecmodbitrate().size();canbitcount ++)
        {
            CanModeBitrate canmobita = CanSettings::getvecmodbitrate().at(canbitcount);
            //delete the same data
            if(canmobita.canname.toStdString()==canmbr.bitrate.toStdString())
            {
                getvecmodbitrate().remove(canbitcount);
            }
        }
        getvecmodbitrate().append(canmbr);

    }

    //add new
    return true;
}


//for test
void CanSettings::onActionTest()
{
   // QMessageBox::information(this, tr("测试"), tr("test"));
}



void CanSettings::on_treeViewCan_clicked(const QModelIndex &index)
{
    QString  str;
    str += QStringLiteral("CHOUSE: %1\n row%2,column:%3\n").arg(index.data().toString()).arg(index.parent().data().toString());

    qDebug()<<str;
   // QString  str;
   // str += QStringLiteral("CHOUSE: %1\n row%2,column:%3\n").arg(index.data().toString()).arg(index.parent().data().toString());
   // QMessageBox::information(this,"note",str);

}
//update treeview
 bool CanSettings::updatetreeview(QString &chanelnum)
{
     //clear treeview
     treemodel.clear();
     //initial cansettings tree;
     QString channelnumber = chanelnum;
     //if mainpage close ,then it will close too.
     this->setAttribute(Qt::WA_QuitOnClose,false);
     //tree
     ui->treeViewCan->setMaximumHeight(400);
     ui->treeViewCan->header()->hide();
     //treemodel.setHorizontalHeaderLabels(QStringList()<<QStringLiteral("Networks"));
     QStandardItem *para_inv_root = treemodel.invisibleRootItem();
     QStandardItem *inv_root = new QStandardItem(QIcon(":/res/nw.ico"),QString("Networks"));
     para_inv_root->appendRow(inv_root);
     QStandardItem *item = new QStandardItem(QIcon(":/res/nw.ico"),QString("CAN Networks"));
     inv_root->appendRow(item); //添加第一层节点
     QFont *fontitem=new QFont();
     fontitem->setPointSize(14);
     item->setFont(*fontitem);

     item->setCheckable(true);
     for (int i = 0; i < channelnumber.toInt(); ++i)
     {
         QStandardItem *itemcan= new QStandardItem(QIcon(":/res/nw.ico"),QString("CAN")+QString("%0").arg(i+1));
         itemcan->setCheckable(true);
         itemcan->setFont(*fontitem);
         item->appendRow(itemcan); //
         QStandardItem *item_sub_setup = new QStandardItem(QIcon(":/res/setup.ico"),QString("Setup")); //
         itemcan->appendRow(item_sub_setup);
         item_sub_setup->setCheckable(true);
         item_sub_setup->setFont(*fontitem);
         QStandardItem *item_sub_nodes = new QStandardItem(QIcon(":/res/nodes.ico"),QString("Nodes")); //
         itemcan->appendRow(item_sub_nodes);
         item_sub_nodes->setCheckable(true);
         item_sub_nodes->setFont(*fontitem);
         QStandardItem *item_sub_daba = new QStandardItem(QIcon(":/res/db.ico"),QString("DateBases")); //
         itemcan->appendRow(item_sub_daba);
         item_sub_daba->setCheckable(true);
         item_sub_daba->setFont(*fontitem);
         //commit
         // QStandardItem *item_sub_IG= new QStandardItem(QIcon(":/res/IG.ico"),QString("IG")); //
         // itemcan->appendRow(item_sub_IG);
         // item_sub_IG->setCheckable(true);
         // item_sub_IG->setFont(*fontitem);
         // item_sub_IG->setCheckState(Qt::Checked);
     }

     ui->treeViewCan->setStyle(QStyleFactory::create("windows"));
     ui->treeViewCan->setModel(  &treemodel );
     ui->treeViewCan->setEditTriggers(QAbstractItemView::NoEditTriggers);
     //set menu
     ui->treeViewCan->setContextMenuPolicy(Qt::CustomContextMenu);
     connect( ui->treeViewCan, &QTreeView::customContextMenuRequested, this, &CanSettings::onTreeViewMenuRequested);
     ui->treeViewCan->expandAll();
     return true;
}


void CanSettings::on_cansettingpushButtonok_clicked()
{
    //store can mode 、can bit rate
    if(ui->canlineEditBitRate->text() =="")
    {
        QMessageBox::warning(this, tr("Tips"), tr("Please try again!"));
        close();
    }
    bool isint=false;
    bool isfloat=false;
    bool isdouble=false;
    qDebug()<<"text bitrate"<<ui->canlineEditBitRate->text();
    qDebug()<<ui->canlineEditBitRate->text().toInt(&isint);
    qDebug()<<ui->canlineEditBitRate->text().toFloat(&isfloat);
    qDebug()<<ui->canlineEditBitRate->text().toDouble(&isdouble);
    if(!(isint ||isfloat||isdouble ))
    {
        QMessageBox::warning(this, tr("Error"), tr("Please try again!"));
        return;
    }

    if(getcanfilemap().size() == 0)
    {
        QMessageBox::warning(this, tr("Error"), tr("Please create channels or add database *.dbc files!"));
        return;

    }
    QString cantype;
    QString canname;
    QString canmode;
    QString canbitrate;
    //assign
    cantype = ui->labCanType_Info->text();
    canmode     = ui->comboBoxcanmode->currentText();
    canbitrate  = ui->canlineEditBitRate->text();
    canname     = ui->groupBoxCanInfo->title();
    CanSettings::CanModeBitrate canmodebitrate;
    canmodebitrate.bitrate  =canbitrate;
    canmodebitrate.mode     = canmode;
    canmodebitrate.canname  =canname;
    canmodebitrate.cantype  =cantype;
    //save canname canmode canbitrate to vecmodbitrate.
    setvecmodbitrate(canmodebitrate);
    QMessageBox::information(this, tr("Tips"), tr("Setting successfully!"));
    close();
}

void CanSettings::on_cansettingpushButtonCancel_clicked()
{
    close();
}

